#pragma once

#include "tools/ManagerFactory/BaseManager.h"
#include "BaseDriver.h"
#include <unordered_map>

using DriverMap = std::unordered_map<std::string, BaseDriverPtr>;

class DriverManager : public BaseManager
{
public:
    DriverManager(const std::string& name = "") : BaseManager(name) {}
    ~DriverManager() = default;

    bool Init() override;

    template <typename T>
    bool RegisterDriver(const std::string& name = typeid(T).name())
    {
        if (std::is_base_of<BaseDriver, T>::value == false)
        {
            return false;
        }

        auto it = m_drivers.find(name);
        if (it != m_drivers.end())
        {
            return false;
        }

        BaseDriverPtr driverPtr = std::make_shared<T>(name);
        if (driverPtr == nullptr)
        {
            return false;
        }

        auto ret = m_drivers.insert({driverPtr->GetName(), driverPtr});
        return ret.second;
    }

    template <typename T>
    std::shared_ptr<T> GetDriver(const std::string& name = typeid(T).name())
    {
        if (std::is_base_of<BaseDriver, T>::value == false)
        {
            return nullptr;
        }

        auto it = m_drivers.find(name);
        if (it == m_drivers.end())
        {
            return nullptr;
        }

        return std::dynamic_pointer_cast<T>(it->second);
    }

protected:
    DriverMap m_drivers;
};

using DriverManagerPtr = std::shared_ptr<DriverManager>;